package com.minimalist.lindi.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Assert;
import com.minimalist.common.config.exception.BusinessException;
import com.minimalist.common.config.mybatis.bo.PageResp;
import com.minimalist.common.entity.basic.vo.file.FileVO;
import com.minimalist.common.entity.lindi.po.LindiPurchaseIndexRecord;
import com.minimalist.common.entity.lindi.po.LindiPurchaseIndexRecordFile;
import com.minimalist.common.entity.lindi.po.LindiPurchaseTownIndex;
import com.minimalist.common.entity.lindi.vo.purchaseindexrecord.LindiPurchaseIndexRecordQueryVO;
import com.minimalist.common.entity.lindi.vo.purchaseindexrecord.LindiPurchaseIndexRecordVO;
import com.minimalist.common.entity.lindi.vo.purchasetownindex.LindiPurchaseTownIndexVO;
import com.minimalist.common.enums.lindi.LindiPurchaseIndexRecordEnum;
import com.minimalist.common.feign.client.basic.FileFeignClient;
import com.minimalist.common.response.R;
import com.minimalist.common.utils.UnqIdUtil;
import com.minimalist.lindi.manager.LindiPurchaseIndexRecordManager;
import com.minimalist.lindi.mapper.LindiPurchaseIndexRecordMapper;
import com.minimalist.lindi.mapper.LindiPurchaseTownIndexMapper;
import com.minimalist.lindi.service.LindiPurchaseIndexRecordService;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 林地指标平台_购买指标记录表 服务层实现。
 *
 * @author 11987
 * @since 2025-05-12
 */
@Service
public class LindiPurchaseIndexRecordServiceImpl extends ServiceImpl<LindiPurchaseIndexRecordMapper, LindiPurchaseIndexRecord> implements LindiPurchaseIndexRecordService{

    @Autowired
    private LindiPurchaseIndexRecordMapper mapper;

    @Autowired
    private LindiPurchaseIndexRecordManager lindiPurchaseIndexRecordManager;

    @Autowired
    private FileFeignClient fileFeignClient;

    @Autowired
    private LindiPurchaseTownIndexMapper lindiPurchaseTownIndexMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addPurchaseIndexRecord(LindiPurchaseIndexRecordVO purchaseIndexRecordVO){
        LindiPurchaseIndexRecord record = BeanUtil.copyProperties(purchaseIndexRecordVO
                , LindiPurchaseIndexRecord.class);
        record.setPurchaseIndexRecordId(UnqIdUtil.uniqueId());
        int insert = mapper.insert(record, true);
        Assert.isTrue(insert == 1, () -> new BusinessException(
                LindiPurchaseIndexRecordEnum.ErrorMsgEnum.ADD_PURCHASE_INDEX_RECORD_ERROR
                        .getDesc()));

        // 保存购买项目
        if (purchaseIndexRecordVO.getPurchaseItems() != null && !purchaseIndexRecordVO.getPurchaseItems().isEmpty()){
            List<LindiPurchaseTownIndex> purchaseTownIndexList = purchaseIndexRecordVO.getPurchaseItems().stream()
                    .map(item -> LindiPurchaseTownIndex.builder()
                            .purchaseIndexRecordId(record.getPurchaseIndexRecordId())
                            .purchaseTownIndexId(UnqIdUtil.uniqueId())
                            .townName(item.getTownName())
                            .townIndex(item.getTownIndex())
                            .fileId(item.getFileId())
                            .build())
                    .toList();
            purchaseTownIndexList.forEach(lindiPurchaseTownIndexMapper::insert);
        }

        lindiPurchaseIndexRecordManager.insertPurchaseIndexRecordFiles(
                purchaseIndexRecordVO.getFileIds()
                , record.getPurchaseIndexRecordId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePurchaseIndexRecordByPurchaseIndexRecordId(Long purchaseIndexRecordId){
        LindiPurchaseIndexRecord record = mapper.selectPurchaseIndexRecordByPurchaseIndexRecordId(purchaseIndexRecordId);
        Assert.notNull(record, () -> new BusinessException(LindiPurchaseIndexRecordEnum
                .ErrorMsgEnum.PURCHASE_INDEX_RECORD_NOT_FOUND.getDesc()));

        // 删除购买项目
        lindiPurchaseTownIndexMapper.deleteByPurchaseIndexRecordId(purchaseIndexRecordId);

        lindiPurchaseIndexRecordManager
                .deletePurchaseIndexRecordFilesByPurchaseIndexRecordId(
                        purchaseIndexRecordId);
        int delete = mapper.delete(record);
        Assert.isTrue(delete == 1, () -> new BusinessException(
                LindiPurchaseIndexRecordEnum.ErrorMsgEnum
                        .DELETE_PURCHASE_INDEX_RECORD_ERROR.getDesc()));
        List<Long> purchaseIndexRecordFileList =
                lindiPurchaseIndexRecordManager.getPurchaseIndexRecordFileListByPurchaseIndexRecordId(
                        purchaseIndexRecordId).stream().map(
                        LindiPurchaseIndexRecordFile::getFileId).toList();
        R<Void> result = fileFeignClient.deleteBatchFiles(purchaseIndexRecordFileList);
        Assert.isTrue(result.getCode() == 200, () -> new BusinessException(
                LindiPurchaseIndexRecordEnum.ErrorMsgEnum
                        .DELETE_PURCHASE_INDEX_RECORD_FILE_ERROR.getDesc()));
        lindiPurchaseIndexRecordManager
                .deletePurchaseIndexRecordFilesByPurchaseIndexRecordId(
                        purchaseIndexRecordId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePurchaseIndexRecordByPurchaseIndexRecordId(
            LindiPurchaseIndexRecordVO purchaseIndexRecordVO){
        LindiPurchaseIndexRecord record = mapper
                .selectPurchaseIndexRecordByPurchaseIndexRecordId(purchaseIndexRecordVO
                        .getPurchaseIndexRecordId());
        Assert.notNull(record, () -> new BusinessException(LindiPurchaseIndexRecordEnum
                .ErrorMsgEnum.PURCHASE_INDEX_RECORD_NOT_FOUND.getDesc()));
        BeanUtil.copyProperties(purchaseIndexRecordVO, record
                , CopyOptions.create().ignoreNullValue());
        int update = mapper.update(record);
        Assert.isTrue(update == 1, () -> new BusinessException(
                LindiPurchaseIndexRecordEnum.ErrorMsgEnum
                        .UPDATE_PURCHASE_INDEX_RECORD_ERROR.getDesc()));

        // 更新购买项目：先删除再新增
        lindiPurchaseTownIndexMapper.deleteByPurchaseIndexRecordId(purchaseIndexRecordVO.getPurchaseIndexRecordId());
        if (purchaseIndexRecordVO.getPurchaseItems() != null && !purchaseIndexRecordVO.getPurchaseItems().isEmpty()){
            List<LindiPurchaseTownIndex> purchaseTownIndexList = purchaseIndexRecordVO.getPurchaseItems().stream()
                    .map(item -> LindiPurchaseTownIndex.builder()
                            .purchaseIndexRecordId(purchaseIndexRecordVO.getPurchaseIndexRecordId())
                            .purchaseTownIndexId(UnqIdUtil.uniqueId())
                            .townName(item.getTownName())
                            .townIndex(item.getTownIndex())
                            .fileId(item.getFileId())
                            .build())
                    .toList();
            purchaseTownIndexList.forEach(lindiPurchaseTownIndexMapper::insert);
        }

        lindiPurchaseIndexRecordManager
                .deletePurchaseIndexRecordFilesByPurchaseIndexRecordId(
                        purchaseIndexRecordVO.getPurchaseIndexRecordId());
        lindiPurchaseIndexRecordManager.insertPurchaseIndexRecordFiles(
                purchaseIndexRecordVO.getFileIds()
                , purchaseIndexRecordVO.getPurchaseIndexRecordId());
    }

    @Override
    public PageResp<LindiPurchaseIndexRecordVO> getPagePurchaseIndexRecordList(
            LindiPurchaseIndexRecordQueryVO queryVO){
        //分页查询
        Page<LindiPurchaseIndexRecord> recordPage = mapper
                .selectPagePurchaseIndexRecordList(queryVO);
        //数据转换
        // 先查询所有记录的购买项目
        List<Long> recordIds = recordPage.getRecords().stream()
                .map(LindiPurchaseIndexRecord::getPurchaseIndexRecordId)
                .toList();
        
        // 批量查询所有购买项目
        List<LindiPurchaseTownIndex> allPurchaseItems = recordIds.stream()
                .flatMap(recordId -> lindiPurchaseTownIndexMapper.selectByPurchaseIndexRecordId(recordId).stream())
                .toList();
        
        // 批量查询所有购买项目的文件信息
        List<Long> allPurchaseItemFileIds = allPurchaseItems.stream()
                .map(LindiPurchaseTownIndex::getFileId)
                .filter(fileId -> fileId != null)
                .distinct()
                .toList();
        
        R<List<FileVO>> allPurchaseItemFiles = fileFeignClient.getFileListByFileIds(allPurchaseItemFileIds);
        List<FileVO> allPurchaseItemFileList = allPurchaseItemFiles.getData() != null ? allPurchaseItemFiles.getData() : List.of();
        
        List<LindiPurchaseIndexRecordVO> voList = recordPage.getRecords().stream()
                .map(record -> {
                    LindiPurchaseIndexRecordVO vo = BeanUtil.copyProperties(record, LindiPurchaseIndexRecordVO.class);
                    // 查询购买项目
                    List<LindiPurchaseTownIndex> purchaseItems = allPurchaseItems.stream()
                            .filter(item -> item.getPurchaseIndexRecordId().equals(record.getPurchaseIndexRecordId()))
                            .toList();
                    
                    List<LindiPurchaseTownIndexVO> purchaseItemVOs = purchaseItems.stream()
                            .map(item -> {
                                FileVO fileVO = allPurchaseItemFileList.stream()
                                        .filter(file -> file.getFileId().equals(item.getFileId()))
                                        .findFirst()
                                        .orElse(null);
                                return new LindiPurchaseTownIndexVO(item.getPurchaseTownIndexId(), item.getPurchaseIndexRecordId(), 
                                        item.getTownName(), item.getTownIndex(), item.getFileId(), fileVO);
                            })
                            .collect(Collectors.toList());
                    vo.setPurchaseItems(purchaseItemVOs);
                    return vo;
                }).toList();
        return new PageResp<>(voList, recordPage.getTotalRow());
    }

    @Override
    public LindiPurchaseIndexRecordVO getPurchaseIndexRecordByPurchaseIndexRecordId(
            Long purchaseIndexRecordId){
        LindiPurchaseIndexRecord record = mapper
                .selectPurchaseIndexRecordByPurchaseIndexRecordId(
                        purchaseIndexRecordId);
        Assert.notNull(record, () -> new BusinessException(
                LindiPurchaseIndexRecordEnum.ErrorMsgEnum
                        .PURCHASE_INDEX_RECORD_NOT_FOUND.getDesc()));

        // 查询购买项目
        List<LindiPurchaseTownIndex> purchaseItems = lindiPurchaseTownIndexMapper.selectByPurchaseIndexRecordId(purchaseIndexRecordId);
        
        // 批量查询购买项目的文件信息
        List<Long> purchaseItemFileIds = purchaseItems.stream()
                .map(LindiPurchaseTownIndex::getFileId)
                .filter(fileId -> fileId != null)
                .distinct()
                .toList();
        
        R<List<FileVO>> purchaseItemFiles = fileFeignClient.getFileListByFileIds(purchaseItemFileIds);
        List<FileVO> purchaseItemFileList = purchaseItemFiles.getData() != null ? purchaseItemFiles.getData() : List.of();
        
        List<LindiPurchaseTownIndexVO> purchaseItemVOs = purchaseItems.stream()
                .map(item -> {
                    FileVO fileVO = purchaseItemFileList.stream()
                            .filter(file -> file.getFileId().equals(item.getFileId()))
                            .findFirst()
                            .orElse(null);
                    return new LindiPurchaseTownIndexVO(item.getPurchaseTownIndexId(), item.getPurchaseIndexRecordId(), 
                            item.getTownName(), item.getTownIndex(), item.getFileId(), fileVO);
                })
                .collect(Collectors.toList());

        List<Long> fileIdList =
                lindiPurchaseIndexRecordManager.getPurchaseIndexRecordFileListByPurchaseIndexRecordId(
                        purchaseIndexRecordId).stream().map(
                        LindiPurchaseIndexRecordFile::getFileId).toList();
        R<List<FileVO>> files = fileFeignClient.getFileListByFileIds(fileIdList);
        LindiPurchaseIndexRecordVO lindiPurchaseIndexRecordVO = BeanUtil
                .copyProperties(record, LindiPurchaseIndexRecordVO.class);
        lindiPurchaseIndexRecordVO.setPurchaseItems(purchaseItemVOs);
        lindiPurchaseIndexRecordVO.setFiles(files.getData());
        return lindiPurchaseIndexRecordVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePurchaseIndexRecordFileByFileId(Long fileId){
        R<Void> result = fileFeignClient.deleteFile(fileId);
        Assert.isTrue(result.getCode() == 200, () -> new
                BusinessException(LindiPurchaseIndexRecordEnum.ErrorMsgEnum
                .DELETE_PURCHASE_INDEX_RECORD_FILE_ERROR.getDesc()));
        lindiPurchaseIndexRecordManager.deletePurchaseIndexRecordFilesByFileId(fileId);
    }
}
